package com.rz.htk.order.listeners;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSONObject;
import com.rz.core.config.RedisKeys;
import com.rz.core.kit.RedisKit;
import com.rz.htk.config.RedisKeyConfig;
import com.rz.htk.dubbo.service.DictDataService;
import com.rz.htk.order.entity.Commodity;
import com.rz.htk.order.entity.Order;
import com.rz.htk.order.entity.OrderRecord;
import com.rz.htk.order.entity.excel.OrderExcelModel;
import com.rz.htk.order.service.IOrderService;
import com.rz.htk.postal.service.IExpressCodeService;
import com.rz.htk.product.entity.ProductPrice;
import com.rz.htk.product.service.IProductPriceService;
import com.rz.htk.product.service.IProductService;
import com.rz.htk.type.OrderState;
import consumer.model.SysDictData;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * author: Rui.Zhou
 * date: 2019-04-13
 * Description:
 */
public class OrderImportListener extends AnalysisEventListener {
    private static final String format = "yyyy-MM-dd";
    private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<>();

    private IOrderService IOrderService;
    private RedisKit redisKit;
    private IExpressCodeService expressCodeService;
    private IProductPriceService productPriceService;
    private List<String> errorMsgs = new ArrayList<>();
    private Integer crteMngId;
    private IProductService iProductService;
    private DictDataService dictDataService;
    private String consumerCode;

    public OrderImportListener(IOrderService IOrderService, IExpressCodeService expressCodeService, IProductPriceService productPriceService, IProductService iProductService, DictDataService dictDataService, RedisKit redisKit, Integer crteMngId, String consumerCode) {
        this.IOrderService = IOrderService;
        this.redisKit = redisKit;
        this.expressCodeService = expressCodeService;
        this.productPriceService = productPriceService;
        this.iProductService = iProductService;
        this.dictDataService = dictDataService;
        this.crteMngId = crteMngId;
        this.consumerCode =consumerCode;

    }

    public List<String> getErrorMsgs() {
        return errorMsgs;
    }

    private List<Order> orders = new ArrayList<>();
    private List<Commodity> commodities = new ArrayList<>();
    private List<OrderRecord> records = new ArrayList<>();
    private Map<String, String> rowUniqeMap = new HashMap<>();
    private Map<String, String> orderCodeMap = new HashMap<>();
    private Map<String, String> expressCodeMap = new HashMap<>();
    private Map<String, String> productMap = new HashMap<>();
    private Map<String, String> unitMap = new HashMap<>();
    private String code = "";

    @Override
    public void invoke(Object object, AnalysisContext context) {
        OrderExcelModel orderExcelModel = (OrderExcelModel) object;
        if(!StringUtils.isEmpty(orderExcelModel.getRecipientsAddress())){
            String address = orderExcelModel.getRecipientsAddress().trim();
            address = address.replaceAll(" ","");
            orderExcelModel.setRecipientsAddress(address);
        }
        boolean isEmptyExcel = valiateIsEmpty(orderExcelModel);
        if (!isEmptyExcel) {
            // String mapKey = orderExcelModel.getCommodityCode() + orderExcelModel.getRecipientsPhone() + orderExcelModel.getSenderPhone();

            if (StringUtils.isEmpty(orderExcelModel.getCommodityCode())) {
                if (StringUtils.isEmpty(orderExcelModel.getCommodityName())) {
                    errorMsgs.add("第" + context.getCurrentRowNum() + "行第2列订单号不能为空！");
                } else {
                    if (expressCodeMap.containsKey(code + "-1")&&StringUtils.isEmpty(orderExcelModel.getPrints())) {
                        Commodity commodity = new Commodity();
                        commodity.setAmount(orderExcelModel.getAmount());
                        commodity.setCommodityName(orderExcelModel.getCommodityName());
                        if (!StringUtils.isEmpty(orderExcelModel.getCommodityValue())) {
                            commodity.setCommodityValue(Double.valueOf(orderExcelModel.getCommodityValue()));
                        }
                        if (!StringUtils.isEmpty(orderExcelModel.getCommodityWeight())) {
                            commodity.setWeight(Double.parseDouble(orderExcelModel.getCommodityWeight()));
                        }
                        commodity.setCreationTime(LocalDateTime.now());
                        commodity.setCrteMngId(crteMngId);
                        commodity.setDelFlag(0);
                        commodity.setCommodityCode(code);
                        commodities.add(commodity);
                    }
                }
            } else {
                expressCodeMap.put(orderExcelModel.getCommodityCode() + "-2", orderExcelModel.getCommodityCode() + "-2");
                if (!redisKit.containsKeyHash(RedisKeyConfig.ORDER_CODE, orderExcelModel.getCommodityCode())) {
                    //如果订单号在数据库没有，则添加新订单，如果有，就直接跳过此条数据
                    //添加新订单
                    expressCodeMap.put(orderExcelModel.getCommodityCode() + "-1", orderExcelModel.getCommodityCode() + "-1");
                    if(StringUtils.isEmpty(orderExcelModel.getPrints())) {
                        valiate(context.getCurrentRowNum(), orderExcelModel);
                    }
                    Order order = new Order();
                    OrderRecord orderRecord = new OrderRecord();
                    BeanUtils.copyProperties(orderExcelModel, order, "times");
                    if (orderExcelModel.getTimes() != null) {
                        SimpleDateFormat sdf = null;
                        sdf = threadLocal.get();
                        if(sdf==null){
                            sdf = new SimpleDateFormat(format);
                        }
                        order.setTimes(sdf.format(orderExcelModel.getTimes()));
                    }
                    order.setCreationTime(LocalDateTime.now());
                    order.setCrteMngId(crteMngId);
                    order.setConsumerCode(consumerCode);
                    order.setState(OrderState.dairuku);
                    order.setDelFlag(0);

                    orderRecord.setState(OrderState.dairuku);
                    orderRecord.setCrteMngId(crteMngId);
                    orderRecord.setCreationTime(LocalDateTime.now());
                    orderRecord.setCommodityCode(order.getCommodityCode());

                    code = order.getCommodityCode();
                    records.add(orderRecord);
                    if (StringUtils.isEmpty(orderExcelModel.getLuXiang())) {
                        errorMsgs.add("第" + context.getCurrentRowNum() + "行，第16列路线不能为空！");
                    } else {
                        if (redisKit.containsKeyHash(RedisKeyConfig.PRICE, orderExcelModel.getLuXiang())) {
                            Object trans = redisKit.getValueHash(RedisKeyConfig.PRICE, orderExcelModel.getLuXiang());
                            if (trans != null) {
                                ProductPrice productPrice = JSONObject.parseObject(trans.toString(), ProductPrice.class);
                                if ((productPrice.getMaxWeight() > 0 && orderExcelModel.getWeight() > productPrice.getMaxWeight()) || (productPrice.getMinWeight() > 0 && orderExcelModel.getWeight() < productPrice.getMinWeight())) {
                                    errorMsgs.add("第" + context.getCurrentRowNum() + "行，订单重量不在所选产品范围内！");
                                }
                                orderExcelModel.setTransportation(productPrice.getId());
                                if (StringUtils.isEmpty(orderExcelModel.getAfterCode())) {
                                    String afterCode = expressCodeService.getExpressCode(orderExcelModel.getTransportation());
                                    if (StringUtils.isEmpty(afterCode)) {
                                        errorMsgs.add("第" + context.getCurrentRowNum() + "行，根据路线未能获取到快递单号！");
                                    } else {
                                        orderExcelModel.setAfterCode(afterCode);
                                        order.setAfterCode(afterCode);
                                        expressCodeMap.put(afterCode, RedisKeyConfig.EXPRESS_CODE_QUEUE + productPrice.getPrdCode() + "_" + productPrice.getExpressType());
                                    }
                                }
                                order.setTransportation(orderExcelModel.getTransportation());
                                order.setTotalPrices(productPriceService.quote(order));
                                //设置产品编码
                                order.setPrdCode(productPrice.getPrdCode());
                                if (!productMap.containsKey(productPrice.getPrdCode())) {
                                    productMap.put(productPrice.getPrdCode(), iProductService.getProductByCode(productPrice.getPrdCode()).getUnit());
                                }
                                if (!unitMap.containsKey(productMap.get(productPrice.getPrdCode()))) {
                                    SysDictData dictData = dictDataService.getByCode("unit_" + productMap.get(productPrice.getPrdCode()));
                                    if (dictData != null) {
                                        unitMap.put(productPrice.getPrdCode(), dictData.getDictdataName());
                                    }
                                }
                                order.setUnit(unitMap.get(productPrice.getPrdCode()));
                            } else {
                                errorMsgs.add("第" + context.getCurrentRowNum() + "行，第16列路线在缓存中未找到！");
                            }
                        } else {
                            errorMsgs.add("第" + context.getCurrentRowNum() + "行，第16列路线不存在！");
                        }
                    }
                    orders.add(order);

                    //  orderCodeMap.put(orderExcelModel.getCommodityCode(),orderExcelModel.getCommodityCode());
                    if(StringUtils.isEmpty(orderExcelModel.getPrints())) {
                        Commodity commodity = new Commodity();
                        commodity.setAmount(orderExcelModel.getAmount());
                        commodity.setCommodityName(orderExcelModel.getCommodityName());
                        if (!StringUtils.isEmpty(orderExcelModel.getCommodityValue())) {
                            commodity.setCommodityValue(Double.valueOf(orderExcelModel.getCommodityValue()));
                        }
                        if (!StringUtils.isEmpty(orderExcelModel.getCommodityWeight())) {
                            commodity.setWeight(Double.parseDouble(orderExcelModel.getCommodityWeight()));
                        }
                        commodity.setCreationTime(LocalDateTime.now());
                        commodity.setCrteMngId(crteMngId);
                        commodity.setDelFlag(0);
                        commodity.setCommodityCode(code);
                        commodities.add(commodity);
                    }
                }
            }
        }
    }

    private void valiate(int rowNum, OrderExcelModel model) {
        //  String mapKey = model.getCommodityCode() + model.getRecipientsPhone() + model.getSenderPhone();
        //   if (!rowUniqeMap.containsKey(mapKey)) {
        if (orderCodeMap.containsKey(model.getCommodityCode())) {
            errorMsgs.add("第" + rowNum + "行的订单号在excel里已存在！");
        }
        if (StringUtils.isEmpty(model.getDestination())) {
            errorMsgs.add("第" + rowNum + "行，第4列目的地不能为空！");
        } else {
            Object desObj = redisKit.getValueHash(RedisKeys.COUNTRY_NAME, model.getDestination());
            if (redisKit.containsKeyHash(RedisKeys.COUNTRY_NAME, model.getDestination())) {
                model.setDestination(desObj.toString());
            } else if (redisKit.containsKeyHash(RedisKeys.COUNTRY_FULL_NAME, model.getDestination())) {
                Object desFullObj = redisKit.getValueHash(RedisKeys.COUNTRY_FULL_NAME, model.getDestination());
                model.setDestination(desFullObj.toString());
            } else {
                errorMsgs.add("第" + rowNum + "行，第4列目的地不存在，请确认简称或者全称书写是否正确！");
            }
        }
        if (model.getWeight() == null||!isDouble(String.valueOf(model.getWeight()))) {
            errorMsgs.add("第" + rowNum + "行，第5列重量不能为空,或非数字！");
        }
        if (StringUtils.isEmpty(model.getRecipientsName())) {
            errorMsgs.add("第" + rowNum + "行，第6列收件人不能为空！");
        }
        if (StringUtils.isEmpty(model.getRecipientsAddress())) {
            errorMsgs.add("第" + rowNum + "行，第9列收件人地址不能为空！");
        }
        if (StringUtils.isEmpty(model.getRecipientsPhone())) {
            errorMsgs.add("第" + rowNum + "行，第11列收件人电话不能为空！");
        }
        if (StringUtils.isEmpty(model.getSenderName())) {
            errorMsgs.add("第" + rowNum + "行，第17列发件人姓名不能为空！");
        }
        if (StringUtils.isEmpty(model.getSenderAddress())) {
            errorMsgs.add("第" + rowNum + "行，第18列发件人地址不能为空！");
        }
        if (StringUtils.isEmpty(model.getSenderPhone())) {
            errorMsgs.add("第" + rowNum + "行，第19列发件人电话不能为空！");
        }
        //   }
        if (StringUtils.isEmpty(model.getCommodityName())) {
            errorMsgs.add("第" + rowNum + "行，第12列物品名称不能为空！");
        }
        if (StringUtils.isEmpty(model.getCommodityValue())||!isDouble(String.valueOf(model.getCommodityValue()))) {
            errorMsgs.add("第" + rowNum + "行，第13列申报价格不能为空,或非数字！");
        }
        if (model.getAmount() == null) {
            errorMsgs.add("第" + rowNum + "行，第14列物品数量不能为空！");
        }
        if (StringUtils.isEmpty(model.getCommodityWeight())||!isDouble(String.valueOf(model.getCommodityWeight()))) {
            errorMsgs.add("第" + rowNum + "行，第15列物品重量不能为空,或非数字！");
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (errorMsgs.size() == 0) {
            IOrderService.saveImportOrders(orders, commodities, records);
        }

        expressCodeMap.forEach((key, value) -> redisKit.leftPush(value, key));

        orders.clear();
        commodities.clear();
        records.clear();
        rowUniqeMap.clear();
        orderCodeMap.clear();
        expressCodeMap.clear();
    }

    private boolean valiateIsEmpty(OrderExcelModel o) {
        try {
            for (Field field : o.getClass().getDeclaredFields()) {
                field.setAccessible(true);//把私有属性公有化
                Object object = field.get(o);
                if (!ObjectUtils.isEmpty(object)) {
                    return false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    public boolean isDouble(String str){
        try{
            Double.parseDouble(str);
            return true;
        }catch (NumberFormatException ex){
            return false;
        }
    }
}